package org.ma1.cripto.aes.operacion;

import org.ma1.cripto.aes.comun.Bloque;
import org.ma1.cripto.aes.comun.ByteUtil;
import org.ma1.cripto.aes.comun.Clave;

public class InvMixColumns implements IOperacion {

	public InvMixColumns(){};
	
	
	public Bloque operacion(Bloque bloque,Clave clave) {
		int[] sp = new int[4];
	    byte b0e = (byte)0x0e, 
	         b0b = (byte)0x0b, 
	         b0d = (byte)0x0d, 
	         b09 = (byte)0x09;
	    
	    byte[][] s=new byte[4][4];
	    //Pasamos el bloque a una matriz 4x4
	    for(int j=0; j<4; j++)
		{
			for(int i=0; i<4; i++)
			{
				s[i][j]=bloque.getByte(j*4+i);
			}
		}
	    
	    for (int c = 0; c < 4; c++) {
	         sp[0] = ByteUtil.getCurrentInstance().producto(b0e, s[0][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b0b, s[1][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b0d, s[2][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b09, s[3][c]);
	         sp[1] = ByteUtil.getCurrentInstance().producto(b09, s[0][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b0e, s[1][c]) 
	         	   ^ ByteUtil.getCurrentInstance().producto(b0b, s[2][c]) 
	         	   ^ ByteUtil.getCurrentInstance().producto(b0d, s[3][c]);
	         sp[2] = ByteUtil.getCurrentInstance().producto(b0d, s[0][c])  
	               ^ ByteUtil.getCurrentInstance().producto(b09, s[1][c])  
	               ^ ByteUtil.getCurrentInstance().producto(b0e, s[2][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b0b, s[3][c]);
	         sp[3] = ByteUtil.getCurrentInstance().producto(b0b, s[0][c]) 
	               ^ ByteUtil.getCurrentInstance().producto(b0d, s[1][c])
	               ^ ByteUtil.getCurrentInstance().producto(b09, s[2][c])
	               ^ ByteUtil.getCurrentInstance().producto(b0e, s[3][c]);
	         for (int i = 0; i < 4; i++) 
	        	 s[i][c] = (byte)(sp[i]);
	    }
	
	    //Pasamos la matriz 4x4 a un bloque
	    for(int j=0; j<Bloque.N/4; j++)
	    {
			for(int i=0; i<4; i++)
			{
				bloque.setByte(j*4+i,s[i][j]);
			}
		}
	    return bloque;
	}
	public String getNombre() {
		return OperacionBuilder.InvMixColumns;
	}
}
